/***************************************************************************
 *   Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net>     *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/


#ifndef GUI_NAVIGATIONSTYLE_H
#define GUI_NAVIGATIONSTYLE_H

// #include <Inventor/C/basic.h>
// #include <Inventor/SbBox2s.h>
// #include <Inventor/SbVec2f.h>
// #include <Inventor/SbVec2s.h>
// #include <Inventor/SbVec3f.h>
// #include <Inventor/SbPlane.h>
// #include <Inventor/SbRotation.h>
// #include <Inventor/SbTime.h>
#include <QCursor>
#include <QEvent>
#include <Base/BaseClass.h>

#include "CKAll.h"

// forward declarations
// class SoEvent;
// class SoQtViewer;
// class SoCamera;
// class SoSensor;
// class SbSphereSheetProjector;
#define MEMOVE				1
#define MELDRECEIVED		2
#define MELURECEIVED		4
#define MERDRECEIVED		8
#define MERURECEIVED		16
#define MEMDRECEIVED		32
#define MEMURECEIVED		64
#define MEROLL				128
#define MELDC_RECEIVED		256
#define MERDC_RECEIVED		512
#define MEMDC_RECEIVED		1024




namespace Gui {

class View3DInventorViewer;
class AbstractMouseSelection;

/**
 * @author Werner Mayer
 */
 class  NavigationStyleEvent : public QEvent
 {
 public:
     NavigationStyleEvent(const Base::Type& s);
     ~NavigationStyleEvent();
     const Base::Type& style() const;
 private:
     Base::Type t;
 };

/**
 * The navigation style base class
 * @author Werner Mayer
 */
class  NavigationStyle : public Base::BaseClass
{
    TYPESYSTEM_HEADER();

public:
    enum ViewerMode {
        IDLE,
        INTERACT,
        ZOOMING,
        BOXZOOM,
        PANNING,
        DRAGGING,
        SPINNING,
        SEEK_WAIT_MODE,
        SEEK_MODE,
        SELECTION
    };

    enum SelectionMode {
        Lasso       = 0,  /**< Select objects using a lasso. */
        Rectangle   = 1,  /**< Select objects using a rectangle. */
        BoxZoom     = 2,  /**< Perform a box zoom. */
        Clip        = 3,  /**< Clip objects using a lasso. */
    };

public:
    NavigationStyle();
    virtual ~NavigationStyle();

    NavigationStyle& operator = (const NavigationStyle& ns);
    void setViewer(View3DInventorViewer*);


    void setAnimationEnabled(const bool enable);
    bool isAnimationEnabled(void) const;

    void startAnimating(const VxVector& axis, float velocity);
    void stopAnimating(void);
    bool isAnimating(void) const;

    void setZoomInverted(bool);
    bool isZoomInverted() const;

    void updateAnimation();
    void redraw();
    
    void setCameraOrientation(const VxVector& rot);
    void boxZoom(const VxBbox& box);
    virtual void viewAll();

    void setViewingMode(const ViewerMode newmode);
    int getViewingMode() const;
    virtual bool processEvent(/*const SoEvent * const ev*/);

//     void setPopupMenuEnabled(const SbBool on);
//     SbBool isPopupMenuEnabled(void) const;

    void startSelection(AbstractMouseSelection*);
    void startSelection(SelectionMode = Lasso);
    void stopSelection();
    bool isSelecting() const;
    //const std::vector<SbVec2s>& getPolygon(SbBool* clip_inner=0) const;

protected:
    void initialize();
    void finalize();

    void interactiveCountInc(void);
    void interactiveCountDec(void);
    int getInteractiveCount(void) const;

    bool isViewing(void) const;
    void setViewing(bool);
    bool isSeekMode(void) const;
    void setSeekMode(bool enable);
    bool seekToPoint(const Vx2DVector screenpos);
    void seekToPoint(const VxVector& scenepos);

    //void reorientCamera(SoCamera * camera, const SbRotation & rot);
    void panCamera(CKCamera * camera,
		             VxVector& camPos,
//                    float vpaspect,
//                    const VxPlane & panplane,
                    Vx2DVector & previous,
                    Vx2DVector & current);
    void pan(CKCamera* camera);
    void panToCenter(const VxPlane & pplane, const Vx2DVector & currpos);
    void zoom(CKCamera * camera, float diffvalue);
    void zoomByCursor(const Vx2DVector & thispos, const Vx2DVector & prevpos);
    void spin(CKCamera* ,const VxVector & pointerpos);
    bool doSpin();

//     SbBool handleEventInForeground(const SoEvent* const e);
     virtual bool processSoEvent(/*const SoEvent * const ev*/);
    virtual void openPopupMenu(const Vx2DVector& position);

    void clearLog(void);
   // void addToLog(const Vx2DVector pos, const SbTime time);

protected:
    struct { // tracking mouse movement in a log
        short size;
        short historysize;
//         SbVec2s * position;
//         SbTime * time;
    } log;

    View3DInventorViewer* viewer;
    ViewerMode currentmode;
     Vx2DVector lastmouseposition;
     VxPlane panningplane;
  //   cktim prevRedrawTime;
     float centerTime;
     bool lockrecenter;
     bool menuenabled;
     bool ctrldown, shiftdown, altdown;
     bool button1down, button2down, button3down;
     bool invertZoom;

    /** @name Mouse model */
    //@{
    AbstractMouseSelection* mouseSelection;
  //  std::vector<SbVec2s> pcPolygon;
  //  SbBool clipInner;
    //@}

    /** @name Spinning data */
    //@{
    //SbBool spinanimatingallowed;
//     int spinsamplecounter;
//     SbRotation spinincrement;
//     SbRotation spinRotation;
//     SbSphereSheetProjector * spinprojector;
    //@}
	protected:
	CKInputManager* mInput;
	CKTimeManager* mTimeManger;
	int         mElapseTime;

	CKBOOL bLeft,bRight,bMiddle;
	Vx2DVector vMousePos;
private:
    struct NavigationStyleP* pimpl;
    friend struct NavigationStyleP;




};

/** Sub-classes of this class appear in the preference dialog where users can
 * choose their favorite navigation style.
 * All other classes that inherit directly from NavigationStyle do not appear
 * in the above dialog.
 * This mechanism is useful to implement special navigation styles which are
 * only needed for certain purposes. Thus, it should not be possible to be
 * choosable by the user 
 * @author Werner Mayer
 */
class  UserNavigationStyle : public NavigationStyle {
    TYPESYSTEM_HEADER();

public:
    UserNavigationStyle(){}
    ~UserNavigationStyle(){}
    virtual const char* mouseButtons(ViewerMode) = 0;
};

class  InventorNavigationStyle : public UserNavigationStyle {
    typedef UserNavigationStyle inherited;

    TYPESYSTEM_HEADER();

public:
    InventorNavigationStyle();
    ~InventorNavigationStyle();
    const char* mouseButtons(ViewerMode);

protected:
    bool processSoEvent(/*const SoEvent * const ev*/);
};

class  CADNavigationStyle : public UserNavigationStyle {
    typedef UserNavigationStyle inherited;

    TYPESYSTEM_HEADER();

public:
    CADNavigationStyle();
    ~CADNavigationStyle();
    const char* mouseButtons(ViewerMode);

public:

	 CKRenderContext* mRct;

protected:
    bool processSoEvent(/*const SoEvent * const ev*/);

private:
    bool lockButton1;
};

} // namespace Gui

#endif // GUI_NAVIGATIONSTYLE_H 
